using System;

using Pegasus.Diagnostics;

namespace Pegasus.Workflow.Service
{
	/// <summary>
	/// Base class for an indivial workflow state
	/// </summary>
	public class WorkflowState
	{
		// Local Instence Values
		private string m_name;
		private string m_displayName;
		private string m_description;

		private Workflow m_workflow;

		/// <summary>
		/// Initializes a new instance of the <see cref="T:WorkflowState"/> class.
		/// </summary>
		/// <param name="name">The state name.</param>
		public WorkflowState( string name )
		{
			// Check Parameters
			ParamCode.AssertNotEmpty( name, "name" );

			m_name = name;
			m_displayName = null;
			m_description = null;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="T:WorkflowState"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="displayName">Name of the display.</param>
		/// <param name="description">The description.</param>
		public WorkflowState( string name, string displayName, string description )
		{
			// Check Parameters
			ParamCode.AssertNotEmpty( name, "name" );
			ParamCode.AssertNotEmpty( displayName, "displayName" );
			ParamCode.AssertNotEmpty( description, "description" );

			m_name = name;
			m_displayName = displayName;
			m_description = description;
		}

		/// <summary>
		/// Gets the name of the state.
		/// </summary>
		/// <value>The name.</value>
		public string Name
		{
			get
			{
				return m_name;
			}
		}

		/// <summary>
		/// Gets the display name state.
		/// </summary>
		/// <value>The state display name.</value>
		public string DisplayName
		{
			get
			{
				return m_displayName;
			}
		}

		/// <summary>
		/// Gets the description.
		/// </summary>
		/// <value>The description.</value>
		public string Description
		{
			get
			{
				return m_description;
			}
		}

		/// <summary>
		/// Gets the workflow this state belongs to.
		/// </summary>
		/// <value>The workflow.</value>
		public Workflow Workflow
		{
			get
			{
				return m_workflow;
			}
		}

		/// <summary>
		/// Gets the context.
		/// </summary>
		/// <value>The context.</value>
		public WorkflowContext Context
		{
			get
			{
				return m_workflow.Context;
			}
		}

		/// <summary>
		/// Sets the workflow.
		/// </summary>
		/// <param name="workflow">The workflow.</param>
		internal void SetWorkflow( Workflow workflow )
		{
			m_workflow = workflow;
		}

		/// <summary>
		/// Fires the intialize complete event.
		/// </summary>
		internal void FireIntializeComplete()
		{
			OnIntializeComplete();
		}

		/// <summary>
		/// Fires the on state enter events.
		/// </summary>
		/// <param name="previousState">Previouse state, null if workflow is just starting.</param>
		internal void FireStateEnter( string previousState )
		{
			// Record Tracking Event
			m_workflow.Context.GetService<WorkflowTrackingService>().RecordStateEntered( m_workflow.Context, m_name, previousState );

			OnStateEnter( previousState );
		}

		/// <summary>
		/// Fires the on state exit events.
		/// </summary>
		/// <param name="nextState">Next state, null if workflow is finishing.</param>
		internal void FireStateExit( string nextState )
		{
			// Record Tracking Event
			m_workflow.Context.GetService<WorkflowTrackingService>().RecordStateExited( m_workflow.Context, m_name, nextState );

			OnStateExit( nextState );
		}

		/// <summary>
		/// Fires the before save event.
		/// </summary>
		internal void FireBeforeSave()
		{
			OnBeforeSave();
		}

		/// <summary>
		/// Called when intialize complete of the workflow is completed.
		/// </summary>
		protected virtual void OnIntializeComplete()
		{
			if( IntializeComplete != null )
			{
				IntializeComplete( this, new WorkflowEventArgs( m_workflow.WorkflowId ) );
			}
		}

		/// <summary>
		/// Called when the state is entered.
		/// </summary>
		/// <param name="previousState">Previouse state, null if workflow is just starting.</param>
		protected virtual void OnStateEnter( string previousState )
		{
			if( StateEnter != null )
			{
				StateEnter( this, new WorkflowStateEventArgs( m_workflow.WorkflowId, previousState ) );
			}
		}

		/// <summary>
		/// Called when the state exiting.
		/// </summary>
		/// <param name="nextState">Next state, null if workflow is finishing.</param>
		protected virtual void OnStateExit( string nextState )
		{
			if( StateExit != null )
			{
				StateExit( this, new WorkflowStateEventArgs( m_workflow.WorkflowId, nextState ) );
			}
		}

		/// <summary>
		/// Called when before the persistence services saves the workflow.
		/// </summary>
		protected virtual void OnBeforeSave()
		{
			if( BeforeSave != null )
			{
				BeforeSave( this, new WorkflowEventArgs( m_workflow.WorkflowId ) );
			}
		}

		/// <summary>
		/// Fired when the initialize of the workflow is complete
		/// </summary>
		public event EventHandler<WorkflowEventArgs> IntializeComplete;

		/// <summary>
		/// Fired when the state is entered.
		/// </summary>
		public event EventHandler<WorkflowStateEventArgs> StateEnter;

		/// <summary>
		/// Fired when the state is exited.
		/// </summary>
		public event EventHandler<WorkflowStateEventArgs> StateExit;

		/// <summary>
		/// Fired just before the workflow is saved by the persistence service
		/// </summary>
		public event EventHandler<WorkflowEventArgs> BeforeSave;
	}
}
